﻿using ByHand.Model;
using ByHand.Services.Code;
using ByHand.Services.Implements;
using ByHand.Services.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Helpers;
using EmailSender;
using Newtonsoft.Json.Linq;

namespace FrontEnd.Controllers
{
    public class OrderController : Controller
    {
        private readonly IOrderService _OrderService;
        private readonly ILogService _LogService;
        private readonly IOrderDetailService _OrderDetailService;
        private readonly ISmsLogService _SmsLogService;
        private readonly IUserService _UserService;
        private readonly IProductService _ProductService;
        private readonly IProductOptionService _ProductOptionService;
        private readonly IGuuAttributeProductService _GuuAttributeProductService;

        public OrderController(IOrderService OrderService, ILogService LogService, IOrderDetailService OrderDetailService, IUserService UserService, ISmsLogService SmsLogService, IProductService ProductService, IProductOptionService ProductOptionService, IGuuAttributeProductService GuuAttributeProductService)
        {
            _OrderService = OrderService;
            _LogService = LogService;
            _OrderDetailService = OrderDetailService;
            _SmsLogService = SmsLogService;
            _UserService = UserService;
            _ProductService = ProductService;
            _ProductOptionService = ProductOptionService;
            _GuuAttributeProductService = GuuAttributeProductService;
        }
        [HttpPost]
        public ActionResult PreOrder()
        {

            var order = new Order();
            var tempID = Request.Form["tempID"];
            var optionsvalue = Request.Form["optionsvalue"];
            var level1 = optionsvalue.Split(';');
            order.ProductID = Convert.ToInt32(Request.Form["productid"]);
            order.ToCityID = Convert.ToInt32(Request.Form["city"]);
            order.ToDistrictID = Convert.ToInt32(Request.Form["district"]);
            order.Quantity = Convert.ToInt32(Request.Form["quantity"]);
            order.ToAddress = Request.Form["address"];
            order.ToPhone = Request.Form["mobile"];
            order.ToEmail = Request.Form["email"];
            order.ToName = Request.Form["name"];
            order.RefID = Convert.ToInt32(Request.Form["refid"]);
            order.RefLocation = Request.Form["reflocation"];

            var orderid = Convert.ToInt32(Request.Form["orderid"]);
            if (orderid != 0)
            {

                var getorder = _OrderService.GetById(orderid);
                if (Utility.CheckIsChanged(getorder, order))
                {
                    getorder.ProductID = order.ProductID;
                    getorder.ToCityID = order.ToCityID;
                    getorder.ToDistrictID = order.ToDistrictID;
                    getorder.Quantity = order.Quantity;
                    getorder.ToAddress = order.ToAddress;
                    getorder.ToPhone = order.ToPhone;
                    getorder.ToEmail = order.ToEmail;
                    getorder.ToName = order.ToName;
                    order = getorder;
                }
                else
                {
                    return Json(new { result = true, id = getorder.ID });
                }
                if (order == null)
                {
                    order = new Order();
                    orderid = 0;
                }
            }

            order.Buyer = order.ToName;
            order.BoughtDate = DateTime.Now;
            order.Price = Convert.ToInt32(Request.Form["price"]);
            order.PayType = (int)EPayType.None;
            order.Status = (int)EOrderStatus.Order_New;

            CheckOrderProblem ck = new CheckOrderProblem();
            if (!order.HasProblem && !ck.CheckTrustName(order.ToName)) order.HasProblem = true;
            if (!order.HasProblem && !ck.CheckTrustAddress(order.ToAddress)) order.HasProblem = true;

            if (User.Identity.IsAuthenticated)
            {
                var user = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
                order.UserID = user.ID;
                bool ischanged = false;
                if (string.IsNullOrWhiteSpace(user.Address))
                {
                    ischanged = true;
                    user.Address = order.ToAddress;
                }
                if (user.CityID == 0)
                {
                    ischanged = true;
                    user.CityID = order.ToCityID;
                }
                if (user.DistrictID == 0)
                {
                    ischanged = true;
                    user.DistrictID = order.ToDistrictID;
                }
                if (string.IsNullOrWhiteSpace(user.Phone))
                {
                    ischanged = true;
                    user.Phone = order.ToPhone;
                }
                if (ischanged)
                {
                    _UserService.Update(user);
                }
            }
            var userlog = "";
            if (User.Identity.IsAuthenticated) userlog = User.Identity.Name;
            if (orderid == 0)
            {
                order.CreatedDate = DateTime.Now;
                order.ModifiedDate = DateTime.Now;
                _OrderService.Add(order);
                var log = new Log()
                {
                    OrderID = order.ID,
                    ActionType = (int)ELogActionType.Create_New_Order,
                    ActionDetail = (int)ELogActionDetail.None,
                    ProductID = order.ProductID,
                    Location = order.RefLocation,
                    RefID = order.RefID == null ? "0" : order.RefID.ToString(),
                    UserName = tempID,
                    UserType = "Customer",
                    DateTime = DateTime.Now,
                    ByHandName = userlog
                };
                _LogService.Add(log);
            }
            else
            {
                order.ModifiedDate = DateTime.Now;
                _OrderService.Update(order);
                var log = new Log()
                {
                    OrderID = order.ID,
                    ActionType = (int)ELogActionType.Edit_Order,
                    ActionDetail = (int)ELogActionDetail.None,
                    ProductID = order.ProductID,
                    Location = order.RefLocation,
                    RefID = order.RefID == null ? "0" : order.RefID.ToString(),
                    UserName = tempID,
                    UserType = "Customer",
                    DateTime = DateTime.Now,
                    ByHandName = userlog
                };
                _LogService.Add(log);
            }
            var details = new List<OrderDetail>();
            if (level1.ToList().Count > 0)
            {
                foreach (var item in level1)
                {
                    if (!string.IsNullOrWhiteSpace(item))
                    {
                        var level2 = item.Split(':');
                        var orderdetail = new OrderDetail()
                        {
                            OrderID = order.ID,
                            ProductID = order.ProductID,
                            OptionsValue = level2[0],
                            Quantity = Convert.ToInt32(level2[1])
                        };
                        details.Add(orderdetail);
                    }
                }
                _OrderDetailService.MaintainDetails(details, order.ID);
            }
            return Json(new { result = true, id = order.ID });
        }
        [HttpPost]
        public ActionResult CheckOutOrder()
        {
            try
            {
                var tempID = Request.Form["tempID"];
                var orderid = Convert.ToInt32(Request.Form["orderid"]);
                var ordertype = Convert.ToInt32(Request.Form["paytype"]);
                var userlog = "";
                if (User.Identity.IsAuthenticated) userlog = User.Identity.Name;
                var order = _OrderService.GetById(orderid);
                order.PayType = ordertype;

                if (ordertype == (int)EPayType.SoHaPay)
                {

                    order.Status = (int)EOrderStatus.Order_WaitPay;
                    _OrderService.Update(order);
                    SaveLog(order, userlog, tempID, "Customer");
                    string urlcheckout = "";
                    SohaPayment pay = new SohaPayment();
                    urlcheckout = pay.BuildCheckoutUrl(RootUrl() + "/Order/ResultPayment?tempid=" + tempID, order.ProductID.ToString(), order.ID.ToString(), Convert.ToInt64(order.Price * order.Quantity), order.ToEmail, order.ToPhone, order.ToAddress);
                    return Json(new { result = true, paytype = ordertype, url = urlcheckout });
                }
                else if (ordertype == (int)EPayType.COD)
                {
                    //add more to do with cod
                    order.Status = (int)EOrderStatus.Order_COD_Wait;
                }
                else if (ordertype == (int)EPayType.BankTransfer)
                {
                    //add more to do with banktransfer option
                    order.Status = (int)EOrderStatus.Order_BankTransfer_Wait;
                }
                _OrderService.Update(order);
                SaveLog(order, userlog, tempID, "Customer");

                return Json(new { result = true, paytype = ordertype });
            }
            catch (Exception)
            {

            }
            return Json(new { result = false });
        }
        private void SaveLog(Order order, string userlog, string tempid, string usertype)
        {
            var log = new Log()
            {
                OrderID = order.ID,
                ActionType = (int)ELogActionType.Checkout_Order,
                ActionDetail = (int)LogHelpers.ConvertPaytype((EPayType)order.PayType),
                ProductID = order.ProductID,
                Location = order.RefLocation,
                RefID = order.RefID == null ? "0" : order.RefID.ToString(),
                UserName = tempid,
                UserType = usertype,
                DateTime = DateTime.Now,
                ByHandName = userlog
            };
            _LogService.Add(log);
        }
        public ActionResult ResultPayment()
        {
            var orderid = Convert.ToInt32(Request["order_code"]);
            var tempid = Request["tempid"];
            var order = _OrderService.GetById(orderid);
            var userlog = "";
            if (User.Identity.IsAuthenticated) userlog = User.Identity.Name;
            var resultreceive = ESohaResult.UnSet;
            if (order != null)
            {
                if (order.Status == (int)EOrderStatus.Order_PaySuccess)
                {
                    ViewData["result"] = "Bạn đã thanh toán thành công rồi.";
                    resultreceive = ESohaResult.HaveDone;
                }
                string error_text = !string.IsNullOrEmpty(Request["error_text"]) ? Request["error_text"] : "";
                SohaPayment pay = new SohaPayment();
                bool check = pay.VerifyReturnUrl();
                string html = "";
                if (check && error_text == "")
                {
                    html += "Cám ơn quý khách, quá trình thanh toán đã được hoàn tất. Chúng tôi sẽ kiểm tra và chuyển hàng sớm!";
                    resultreceive = ESohaResult.Success;
                    var paymenttype = Request["payment_type"];
                    var log = new Log()
                    {
                        OrderID = order.ID,
                        ActionType = (int)ELogActionType.Pay_Success,
                        Location = order.RefLocation,
                        ProductID = order.ProductID,
                        RefID = order.RefID.ToString(),
                        UserName = tempid,
                        UserType = "Customer",
                        DateTime = DateTime.Now,
                        ByHandName = userlog
                    };
                    if (Request["payment_type"] == "1")
                    {
                        order.PayType = (int)EPayType.SoHaPayVisa;
                        log.ActionDetail = (int)ELogActionDetail.Payment_Soha_Visa;
                    }
                    else if (Request["payment_type"] == "2")
                    {
                        order.PayType = (int)EPayType.SoHaPayMaster;
                        log.ActionDetail = (int)ELogActionDetail.Payment_Soha_MasterCard;
                    }
                    else
                    {
                        order.PayType = (int)EPayType.SoHaPay;
                        log.ActionDetail = (int)ELogActionDetail.None;
                    }
                    order.Status = (int)EOrderStatus.Order_PaySuccess;
                    //_OrderService.Update(order);
                    _LogService.Add(log);
                    var p = _ProductService.GetById(order.ProductID);
                    if ((order.IsSmsSended == null || order.IsSmsSended == false)&&(p.GuuID==null||p.GuuID==0))
                    {
                        // sms
                        SmsHelpers smsHelper = new SmsHelpers();
                        string messid = "sms_" + order.ID + "_" + order.Status;
                        string smsresult = "";
                        string smsContent = Resources.Resource.SmsPaySuccessContent.Replace("{order}", order.ID.ToString()).Replace("{total}", (order.Price * order.Quantity).ToString());
                        var smsResultObj = smsHelper.Send(messid, order.ToPhone, smsContent, out smsresult);
                        _SmsLogService.Add(new SmsLog()
                        {
                            DateCreated = DateTime.Now,
                            MessageID = smsResultObj.message_id,
                            OrderID = order.ID,
                            SmsResult = smsresult,
                            Status = smsResultObj.status
                        });
                        // email
                        var tempProduct = _ProductService.GetById(order.ProductID);
                        order.Product = tempProduct;
                        order.OrderDetail = _OrderDetailService.GetByOrder(order.ID);
                        foreach (var item in order.OrderDetail)
                        {
                            item.Product = tempProduct;
                        }
                        Utility.ByHandSendMail(order.ToEmail, Resources.Resource.EmailPaySuccessSubject, EmailBuilder.BuildPayingEmail("byhand", order));
                        //var orderT = _OrderService.GetById(order.ID);
                        order.IsSmsSended = true;
                        order.Product = null;
                        foreach (var item in order.OrderDetail)
                        {
                            item.Product = null;
                        }
                        order.OrderDetail = null;
                        _OrderService.Update(order);
                    }
                    if (p.GuuID != 0 && p.GuuID != null && (order.GuuID == null || order.GuuID == 0))
                    {
                        var odetails = _OrderDetailService.GetByOrder(order.ID);
                        List<int> guuattids = new List<int>();
                        foreach (var item in odetails)
                        {
                            if (item.OptionsValue != "undefined")
                            {
                                string size = "";
                                string color = "";
                                var values = item.OptionsValue.Split('-').Where(s => !String.IsNullOrEmpty(s));
                                foreach (var j in values)
                                {
                                    var val = j.Split('_').Where(s => !String.IsNullOrEmpty(s)).ToArray();
                                    if (val[0] == "Size")
                                    {
                                        size = val[1];
                                    }
                                    if (val[0] == "Color")
                                    {
                                        color = val[1];
                                    }
                                }
                                guuattids.Add(_GuuAttributeProductService.GetGuuID((int)p.GuuID, size, color));
                            }
                        }

                        string url = GuuProduct.CreateGuuOrderUrl((int)p.GuuID, guuattids.ToArray(), order.ToName, order.ToPhone, order.ToEmail, order.ToAddress, order.ToCityID, order.ToDistrictID, 1, 1);
                        var data = GuuProduct.Getjsondata(url);
                        var oobject = JObject.Parse(data); // parse as array
                        var o = _OrderService.GetById(order.ID);
                        foreach (KeyValuePair<String, JToken> ap in oobject)
                        {
                            if (ap.Key == "Status")
                            {
                                int status = Convert.ToInt16((String)ap.Value);
                                o.Status = status == 1 ? (int)EOrderStatus.Order_GuuSuccess : (int)EOrderStatus.Order_GuuFail;
                            }
                            if (ap.Key == "OrderID")
                            {
                                int oID = Convert.ToInt16((String)ap.Value);
                                o.GuuID = oID;
                            }
                        }
                        _OrderService.Update(o);
                    }
                }
                else if (check)
                {
                    html += "Quá trình thanh toán không thành công do lỗi: " + error_text;
                    resultreceive = ESohaResult.Error_BySoha;
                    order.PayType = (int)EPayType.SoHaPay;
                    order.Status = (int)EOrderStatus.Order_PayFail;
                    _OrderService.Update(order);
                    var log = new Log()
                    {
                        OrderID = order.ID,
                        ActionType = (int)ELogActionType.Pay_Failed,
                        ActionDetail = (int)ELogActionDetail.Soha_Failed_BySoha,
                        MoreInfo = error_text,
                        Location = order.RefLocation,
                        ProductID = order.ProductID,
                        RefID = order.RefID.ToString(),
                        UserName = tempid,
                        UserType = "Customer",
                        DateTime = DateTime.Now,
                        ByHandName = userlog
                    };
                    _LogService.Add(log);
                }
                else
                {
                    html += "Thông tin bảo mật không đúng";
                    resultreceive = ESohaResult.Error_ByWrongData;
                    order.PayType = (int)EPayType.SoHaPay;
                    order.Status = (int)EOrderStatus.Order_PayFail;
                    _OrderService.Update(order);
                    var log = new Log()
                    {
                        OrderID = order.ID,
                        ActionType = (int)ELogActionType.Pay_Failed,
                        ActionDetail = (int)ELogActionDetail.Soha_Failed_WrongInfo,
                        Location = order.RefLocation,
                        ProductID = order.ProductID,
                        RefID = order.RefID.ToString(),
                        UserName = tempid,
                        UserType = "Customer",
                        DateTime = DateTime.Now,
                        ByHandName = userlog
                    };
                    _LogService.Add(log);
                }
                ViewData["result"] = html;

                // Có thể lưu lại 2 thông tin dưới đây: mô tả chi tiết về kết quả thanh toán
                string response_description = "";
                if (!string.IsNullOrEmpty(Request["payment_type"]))
                {
                    if (Request["payment_type"] == "1") response_description = pay.GetResponseDescriptionInternational(Request["response_code"]);
                    else if (Request["payment_type"] == "2") response_description = pay.GetResponseDescriptionDomestic(Request["response_code"]);
                }
                string respone_massage = "";
                if (!string.IsNullOrEmpty(Request["response_message"]))
                {
                    respone_massage = Request["response_message"];
                    Response.Write(respone_massage);
                }
                ViewData["response_description"] = response_description;
                ViewData["respone_massage"] = respone_massage;


            }

            order.ToCity = UtilityService.GetAllCities().Where(c => c.ID == order.ToCityID).FirstOrDefault();
            order.ToDistrict = UtilityService.GetAllDistrict().Where(c => c.ID == order.ToDistrictID).FirstOrDefault();
            order.OrderDetail = _OrderDetailService.GetByOrder(order.ID);
            TempData["ResultPayment"] = new SohaResult(resultreceive, order.ID, order);
            return RedirectToAction("Index", "Home");
        }
        public ActionResult ResultPaymentOnByHand(int paytype, int id)
        {
            var resultreceive = ESohaResult.UnSet;
                int guupaytype =0;
            if (paytype == (int)EPayType.COD)
            {
                resultreceive = ESohaResult.COD_Process;
                guupaytype = 2;
            }
            else if (paytype == (int)EPayType.BankTransfer)
            {
                resultreceive = ESohaResult.Bank_Process;
                guupaytype = 3;
            }
            var order = _OrderService.GetById(id);
            var product = _ProductService.GetById(order.ProductID);
            if(product!=null && product.GuuID!=null && product.GuuID !=0){
                var odetails = _OrderDetailService.GetByOrder(order.ID);
                List<int> guuattids = new List<int>();
                foreach (var item in odetails)
                {
                    string size ="";
                    string color = "";
                    var values = item.OptionsValue.Split('-').Where(s => !String.IsNullOrEmpty(s));
                    foreach (var j in values)
                    {
                        if (item.OptionsValue != "undefined")
                        {
                            var val = j.Split('_').Where(s => !String.IsNullOrEmpty(s)).ToArray();
                            if (val[0] == "Size")
                            {
                                size = val[1];
                            }
                            if (val[0] == "Color")
                            {
                                color = val[1];
                            }
                        }
                    }
                    guuattids.Add(_GuuAttributeProductService.GetGuuID((int)product.GuuID, size, color));
                }

                string url = GuuProduct.CreateGuuOrderUrl((int)product.GuuID, guuattids.ToArray(), order.ToName, order.ToPhone, order.ToEmail, order.ToAddress, order.ToCityID, order.ToDistrictID, guupaytype, 1);
                var data = GuuProduct.Getjsondata(url);
                var oobject = JObject.Parse(data); // parse as array
                var o = _OrderService.GetById(order.ID);
                foreach (KeyValuePair<String, JToken> ap in oobject)
                {
                    if (ap.Key == "Status") {
                        int status = Convert.ToInt16((String)ap.Value);
                        o.Status = status == 1 ? (int)EOrderStatus.Order_GuuSuccess : (int)EOrderStatus.Order_GuuFail;
                    }
                    if (ap.Key == "OrderID") {
                        int oID = Convert.ToInt16((String)ap.Value);
                        o.GuuID = oID;
                    }
                }
                _OrderService.Update(o);
            }
            order.ToCity = UtilityService.GetAllCities().Where(c => c.ID == order.ToCityID).FirstOrDefault();
            order.ToDistrict = UtilityService.GetAllDistrict().Where(c => c.ID == order.ToDistrictID).FirstOrDefault();
            order.OrderDetail = _OrderDetailService.GetByOrder(order.ID);
            TempData["ResultPayment"] = new SohaResult(resultreceive, order.ID, order);
            return RedirectToAction("Index", "Home");
        }
        [HttpPost]
        public ActionResult SaveNoteOrder(int orderid, string note)
        {
            var order = _OrderService.GetById(orderid);
            if (order != null)
            {
                order.CustomerNote = note;
                order.ModifiedDate = DateTime.Now;
                _OrderService.Update(order);
                return Json(new { result = true });
            }
            return Json(new { result = false });
        }
        public string RootUrl()
        {
            string url = "";
            if (System.Web.HttpContext.Current.Request.ServerVariables["SERVER_PORT"] == "80")
                url = "http://" + System.Web.HttpContext.Current.Request.ServerVariables["SERVER_NAME"];
            else
                url = "http://" + System.Web.HttpContext.Current.Request.ServerVariables["SERVER_NAME"] + ":" + System.Web.HttpContext.Current.Request.ServerVariables["SERVER_PORT"];
            if (Request.ApplicationPath != "/")
                url += Request.ApplicationPath;
            return url;
        }
    }
}
